﻿/*
*┌────────────────────────────────────────────────┐
*│　描    述：Swagger相关配置，分组，
*│  部    门：Faker开发团队
*│　作    者：static残影                                              
*│　版    本：1.0                                              
*│　创建时间：2020.12.01                        
*└────────────────────────────────────────────────┘
*/
using Abp.Extensions;
using Faker.AbpSolution.Swagger.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Faker.AbpSolution.Swagger
{
    public static class SwaggerConfigurer
    {
        /// <summary>
        /// 配置Swagger
        /// </summary>
        /// <param name="services">注册的服务集</param>
        /// <param name="configuration">配置根</param>
        /// <param name="CurrentHostPath">当前启动的服务目录</param>
        /// <returns></returns>
        public static IServiceCollection AddGroupSwagger(this IServiceCollection services, IConfigurationRoot configuration,string CurrentHostPath)
        {
            // 初始化容器
            ApiContainer.InitContainer();

            // Swagger - Enable this line and the related lines in Configure method to enable swagger UI
            services.AddSwaggerGen(options =>
            {
                // 添加所有分组
                foreach (var model in ApiContainer.Container)
                {
                    options.SwaggerDoc(model.Name, model.OpenApiInfo);
                }
                // 归类API文档 
                options.DocInclusionPredicate((docName, description) => {

                    // 描述分组名称为空则属于默认模块
                    if (docName == SwaggerConst.Default)
                    {
                        // 分组名称为空归属于默认 | 分组名称没有定义到常量中归属于默认
                        if (string.IsNullOrEmpty(description.GroupName))
                            return true;
                        if (!ApiContainer.Container.Any(x => x.Name == description.GroupName))
                        {
                            return true;
                        }
                        return false;
                    }
                    else
                    {
                        return description.GroupName == docName;   // 根据组名称来划分
                    }
                });

                var xmlSwaggerConfig = configuration["Swagger:XmlDocName"];
                //此配置可直接映射application层也可以映射host中控制器那层
                //所有可能出现多个xml name
                //存在多个配置
                if (xmlSwaggerConfig != null)
                {
                    if (xmlSwaggerConfig.Contains(';'))
                    {
                        foreach (var item in xmlSwaggerConfig.Split(';'))
                        {
                            // 查找编译路径下的服务文档
                            if (File.Exists($"{CurrentHostPath}\\{item}.xml"))
                            {
                                options.IncludeXmlComments($"{CurrentHostPath}\\{item}.xml", true);
                            }
                            // 查找插件路径下的服务文档
                            //if (File.Exists($"{currentExecutingPath}\\plugins\\{item}\\{item}.xml"))
                            //{
                            //    options.IncludeXmlComments($"{currentExecutingPath}\\plugins\\{item}\\{item}.xml", true);
                            //}
                        }
                    }
                }

                // Define the BearerAuth scheme that's in use
                options.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme()
                {
                    Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey
                });
            });
            return services;
        }

        /// <summary>
        /// 开启分组
        /// </summary>
        /// <param name="app"></param>
        /// <param name="configuration"></param>
        /// <param name="loggerFactory"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseGroupSwagger(this IApplicationBuilder app, Assembly assembly, IConfigurationRoot configuration, ILoggerFactory loggerFactory)
        {
            // Enable middleware to serve generated Swagger as a JSON endpoint
            app.UseSwagger();

            app.UseSwaggerUI(options =>
            {

                foreach (var model in ApiContainer.Container)
                {
                    options.SwaggerEndpoint(string.Format("{0}swagger/{1}/swagger.json", configuration["App:ServerRootAddress"].EnsureEndsWith('/'), model.Name), model.OpenApiInfo.Title);
                }
                


                options.IndexStream = () => assembly
                    .GetManifestResourceStream("Faker.Solution.Web.Host.wwwroot.swagger.ui.index.html");
            }); // URL: /swagger

            return app;
        }
    }
}
